;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;       Desc: try to enter the long mode.
;       copyright (c) 2014 -
;       BrooksGe
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        
        %include "macro.equ"
        
        org     100h
        [bits   16]
        cli
        xor     eax, eax
        mov     ax, cs
        shl     eax, 4
        mov     ebx, eax
        add     eax, dword [cs:Jmp_to_pm32+2]
        mov     dword [cs:Jmp_to_pm32+2], eax
        mov     eax, ebx
        add     eax, dword [cs:GDT_Base_Addr]
        mov     dword [cs:GDT_Base_Addr], eax
        lgdt    [cs:GDTR_Val]
        mov     eax, cr0
        bts     eax, 0
        mov     cr0, eax
        jmp     $ + 2
        ;==============================
        ;now in 16 bits protected mode
        ;==============================
        mov     ax, Selector_Data
        mov     ds, ax
        mov     es, ax
        mov     gs, ax
        mov     fs, ax
        mov     ax, Selector_Stack
        mov     ss, ax
Jmp_to_pm32:
        jmp     dword Selector_Code:In_pm32
        ;==============================
        ;now in 32 bits protected mode
        ;==============================
        [bits   32]
        align   16
In_pm32:
        ;set the stack at the 0x110000
        mov     esp, 0x110000
        call    near Get_Real_Addr
Get_Real_Addr:
        pop     ebx
        add     ebx, Include_Bin - Get_Real_Addr
        mov     esi, ebx
        add     esi, 4
        mov     edi, 0x200000
        mov     ecx, dword [ebx]
        rep     movsb
        ;copy the 64bits code to mem at 0xa00000
        sub     ebx, Include_Bin - Get_Real_Addr
        add     ebx, Include_LongBin - Get_Real_Addr
        ;
        ;********set the parameter to the entry point******
        ;               Pleae complete it later
        ;void MainEntry(void * file, int lenght, void * destArea, void * entry)
        ;
        push    dword 0xa00000
        push    dword 0xa00000
        push    dword [ebx]
        lea     eax, [ebx+4]
        push    eax
        mov     ebx, 0x200200
        call    ebx
        jmp     $
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;GDTR val
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDTR_Val:
        dw      Length_Of_GDT - 1
GDT_Base_Addr:
        dd      GDT_Empty        
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       Construct the GDT table
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        align   16
GDT_Empty:
CREAT_LEGACY_DESCRIPTOR 0x00000000, 0b00000000000, 0x00000

Selector_Code   equ     $ - GDT_Empty
GDT_Code:
CREAT_LEGACY_DESCRIPTOR 0x00000000, 0b11010011010, 0xfffff

Selector_Data   equ     $ - GDT_Empty
GDT_Data:
CREAT_LEGACY_DESCRIPTOR 0x00000000, 0b11010010010, 0xfffff

Selector_Stack  equ     $ - GDT_Empty
GDT_Stack:
CREAT_LEGACY_DESCRIPTOR 0x00000000, 0b11010010010, 0xfffff

;0x20
Selector_Code64 equ     $ - GDT_Empty
GDT_Code64:
CREAT_LONGMODE_DESCRIPTOR 0x00000000, 0b101010011010, 0xfffff

;0x28
Selector_Data64 equ     $ - GDT_Empty
GDT_Data64:
CREAT_LONGMODE_DESCRIPTOR 0x00000000, 0b101010010010, 0xfffff

;0x30
Selector_Stack64 equ     $ - GDT_Empty
GDT_Stack64:
CREAT_LONGMODE_DESCRIPTOR 0x00000000, 0b101010010010, 0xfffff


Length_Of_GDT   equ     $ - GDT_Empty

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;       This bin is the pm32 flat model image file.
;       Its entery must be the 0x200200. Good Luck!
;       Entry Point defintion:
;       typedef void (* Entry)(void * file, int lenght, void * destArea, void * entry)
;               file: The Addr of the long mode code that needed to load
;               lenght: the file legth
;               destArea: the destination addr used to copy the file to it
;               entry: the entry point of the long mode
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Include_Bin:
Bin_Length      equ     $ - Include_Bin
        dd      Bin_Length_val      
Bin_file        equ     $ - Include_Bin      
        incbin  "pm32stub.exe"
Bin_Length_val  equ     $ - Include_Bin - 4


Include_LongBin:
LongBin_Length  equ     $ - Include_LongBin
        dd      LongBin_Length_val
LongBin_file    equ     $ - Include_LongBin
        incbin  "longmode64check.bin"
LongBin_Length_val  equ     $ - Include_LongBin - 4


        